package me.zhengjie.spider.config;

import lombok.RequiredArgsConstructor;
import me.zhengjie.config.FileProperties;
import me.zhengjie.spider.pool.DownloaderObjectFactory;
import me.zhengjie.spider.pool.DownloaderObjectPool;
import me.zhengjie.spider.util.service.FileDownloader;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PreDestroy;

/**
 * 对象池配置
 *
 * @author Administrator
 */
@Configuration
@RequiredArgsConstructor
public class PoolAutoConfiguration {
    private final RestTemplate restTemplate;
    private final FileProperties fileProperties;

    private static final Integer MAX_IDLE = 10;
    private static final Integer MAX_TOTAL = 50;
    private static final Integer MIN_IDLE = 5;

    private DownloaderObjectPool downloaderObjectPool;

    @ConditionalOnClass({DownloaderObjectFactory.class})
    @Bean
    public DownloaderObjectPool downloaderObjectPool() {
        GenericObjectPoolConfig<FileDownloader> poolConfig = new GenericObjectPoolConfig<>();
        // 最大空闲
        poolConfig.setMaxIdle(MAX_IDLE);
        // 最大总数
        poolConfig.setMaxTotal(MAX_TOTAL);
        // 最小空闲
        poolConfig.setMinIdle(MIN_IDLE);
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        //一定要关闭jmx，不然springboot启动会报已经注册了某个jmx的错误
        poolConfig.setJmxEnabled(false);
        this.downloaderObjectPool = new DownloaderObjectPool(this.getDownloaderObjectFactory(), poolConfig);
        initPool(MAX_IDLE, MAX_TOTAL);
        return this.downloaderObjectPool;
    }

    public DownloaderObjectFactory getDownloaderObjectFactory() {
        return new DownloaderObjectFactory(this.restTemplate, this.fileProperties);
    }

    /**
     * 预先加载testObject对象到对象池中
     *
     * @param initialSize 初始化连接数
     * @param maxIdle     最大空闲连接数
     */
    private void initPool(Integer initialSize, Integer maxIdle) {
        if (initialSize <= 0) {
            return;
        }
        int size = Math.min(initialSize, maxIdle);
        for (int i = 0; i < size; i++) {
            try {
                this.downloaderObjectPool.addObject();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    @PreDestroy
    public void destroy() {
        if (this.downloaderObjectPool != null) {
            this.downloaderObjectPool.close();
        }
    }

}
